Skip to content

XHTTP transport: Add BBR and brutal-force congestion control for H3#5711

Open
Katze-942 wants to merge 5 commits intoXTLS:mainfrom
Katze-942:quic-bbr-optimization
Open

XHTTP transport: Add BBR and brutal-force congestion control for H3#5711
Katze-942 wants to merge 5 commits intoXTLS:mainfrom
Katze-942:quic-bbr-optimization

Conversation

@Katze-942
Copy link

@Katze-942 Katze-942 commented Feb 20, 2026

I noticed that VLESS TLS with XHTTP transport and ALPN H3 is significantly slower (~2x) compared to regular HTTP/2, and decided to investigate.

Turns out quic-go uses Reno congestion control by default, while TCP gets BBR from the Linux kernel - likely a contributing factor. On top of that, quic.ListenEarly was called with nil config, so all QUIC parameters were left at quic-go defaults. The default receive windows (512 KB) can also become a bottleneck on high-bandwidth or high-latency links. (removed: keeping quic-go default window sizes) Hard to say which of these matters most, but together they should make a noticeable difference.

Both BBR and Brutal implementations reuse the existing transport/internet/hysteria/congestion package (BBR is a port of Google's BBR v1 from Chromium, Brutal is from Hysteria2) to avoid code duplication and build on what's already in the codebase.

Also added a "congestion" setting to finalmask.quicParams:

  • "bbr" (default) — BBR congestion control
  • "reno" — quic-go default
  • "force-brutal" — Brutal congestion control (requires "up" field)

"force-brutal" reuses the existing brutal-force sender from the Hysteria transport (transport/internet/hysteria/congestion/brutal). It sends at a fixed rate regardless of packet loss. Requires the "up" field specifying the target upload bandwidth (same format as Hysteria2, e.g. "100 mbps").

{
  "finalmask": {
    "quicParams": {
      "congestion": "force-brutal",
      "up": "100 mbps"
    }
  }
}

@Fangliding
Copy link
Member

这事在加hy传输的时候就该弄了
不过调整QUIC参数是可以被外部观察到的 最开始设计的时候甚至都考虑keepalive特征了改这个是不是有点不太好
我觉得服务端加几行默认bbr就行了 别的不改
cc @RPRX

@LjhAUMEM
Copy link
Contributor

客户端 dialer 可以先不动,服务端可以先默认设个 bbr 先用着,反正目前也没有 cdn 可以 h3 回源

conn window 那些没必要过度追求 hy,保持默认值就好,congestion 可以在以后动客户端 dialer 的时候再加,也就是 protoc 可以先不用修改

@RPRX
Copy link
Member

RPRX commented Feb 21, 2026

目前用的人不多,两边都默认 bbr 就行,quic-go 也不至于一直不加 bbr 吧

@RPRX
Copy link
Member

RPRX commented Feb 21, 2026

@Fangliding @LjhAUMEM 话说 Xray-core 加了 hy2 入站后真的还会有人直接起 XHTTP/3 入站吗,又不是 CDN 支持 h3 回源

所以我觉得给客户端加 bbr 会更有用一些,如果有人弄个 brutal 的话到 CDN 的上行拉满

@LjhAUMEM
Copy link
Contributor

@Fangliding @LjhAUMEM 话说 Xray-core 加了 hy2 入站后真的还会有人直接起 XHTTP/3 入站吗,又不是 CDN 支持 h3 回源

hy 的传输层要求设置个 auth,可能不想设置的会用 xhttph3 吧

目前用的人不多,两边都默认 bbr 就行,quic-go 也不至于一直不加 bbr 吧

两边都默认也行,不过我觉得国内上行 bbr 没啥用

@Fangliding
Copy link
Member

#5549 (comment)

@RPRX
Copy link
Member

RPRX commented Feb 21, 2026

#5549 (comment)

那咋说,XHTTP/3 改成默认上行 cubic、下行 bbr 吗

@gumiruo
Copy link

gumiruo commented Feb 21, 2026

@RPRX xhttp h3也准备能吃bbr了?

@Fangliding
Copy link
Member

我感觉下行默认BBR就行了 别的不用改 就几行代码

@gfw-killer
Copy link

不过调整QUIC参数是可以被外部观察到的 最开始设计的时候甚至都考虑keepalive特征了改这个是不是有点不太好

You like to have no options to tune and the PR has hardcoded parameters to tune
Why not have options so user can tune it the way he likes/needs? like Hy2

QUICConfig: &quic.Config{
InitialStreamReceiveWindow: c.config.InitStreamReceiveWindow,
MaxStreamReceiveWindow: c.config.MaxStreamReceiveWindow,
InitialConnectionReceiveWindow: c.config.InitConnReceiveWindow,
MaxConnectionReceiveWindow: c.config.MaxConnReceiveWindow,
MaxIdleTimeout: time.Duration(c.config.MaxIdleTimeout) * time.Second,
KeepAlivePeriod: time.Duration(c.config.KeepAlivePeriod) * time.Second,
DisablePathMTUDiscovery: c.config.DisablePathMtuDiscovery,
EnableDatagrams: true,
MaxDatagramFrameSize: MaxDatagramFrameSize,
DisablePathManager: true,
},

#5549 (comment)

那咋说,XHTTP/3 改成默认上行 cubic、下行 bbr 吗

I see no CUBIC CC here, quic-go default is Reno and the added CC is BBR
am i missing something?

@Fangliding
Copy link
Member

Why not have options so user can tune it the way he likes/needs? like Hy2

暴露无意义的参数只会使配置选项越来越臃肿 你这么喜欢tune你知道bbr里也有一堆硬编码的经验主义参数吗?
HY2让改只是因为官端让改 实际99%的人不会去动这个配置

@RPRX
Copy link
Member

RPRX commented Feb 21, 2026

不过对于 QUIC 来说长远来看本来就应该可以自己配置 congestion 参数,可能应该搞 tlsSessings 里面

这个 PR 的话先把两端都改为默认 bbr 吧,其它的以后再说

@Katze-942
Copy link
Author

Should I remove the custom QUIC receive window sizes (2/16/5/32 MB) and revert to quic-go defaults to avoid an externally observable fingerprint?


请问是否需要移除自定义的 QUIC 接收窗口大小(2/16/5/32 MB),恢复为 quic-go 默认值,以避免外部可观测的指纹特征?

@Katze-942
Copy link
Author

不过对于 QUIC 来说长远来看本来就应该可以自己配置 congestion 参数,可能应该搞 tlsSessings 里面

这个 PR 的话先把两端都改为默认 bbr 吧,其它的以后再说

In the current PR, BBR is already set as the default for both sides. I can move the congestion setting to tlsSettings if needed.


在当前 PR 中,两端已默认使用 BBR。如果需要,我可以将 congestion 配置移到 tlsSettings 中。

@RPRX
Copy link
Member

RPRX commented Feb 22, 2026

其实我觉得 quic-go 本身就很特征了,加上 Hy2 搞出的运营商 UDP QoS,XHTTP/3 现在没多少人用所以还好吧

往 tlsSettings 里加 QUIC 参数的话 Hy2 传输层也要改,所以我的意思是这个 PR 先别管这些,晚点交给 @LjhAUMEM

@LjhAUMEM
Copy link
Contributor

LjhAUMEM commented Feb 22, 2026

在这里改我也没啥问题,要不直接把 hy 的 congestion 逻辑复制一个过来,也别移到 tls 设置里了

只是对于 conn window 那些我有点犹豫,默认值应该就行,应该没必要完全对齐

@Katze-942
Copy link
Author

Should I make the window sizes configurable in the config rather than hardcoded?


是否需要将 window sizes 做成可配置的,而不是硬编码在代码中?

@LjhAUMEM
Copy link
Contributor

LjhAUMEM commented Feb 22, 2026

Should I make the window sizes configurable in the config rather than hardcoded?

是否需要将 window sizes 做成可配置的,而不是硬编码在代码中?

Simply remove these hard-coded conn windows.

If you want congestion configuration, add the force-brutal option as well (this may require an additional up/rate/bandwidth field); otherwise, removing the congestion configuration only retains the default bbr.

@Katze-942 Katze-942 changed the title XHTTP transport: Add BBR congestion control and tune QUIC receive windows for H3 XHTTP transport: Add BBR congestion control for H3 Feb 22, 2026
@Katze-942
Copy link
Author

Removed custom QUIC receive window sizes, using quic-go defaults now.

I can add force-brutal too. Hysteria2 uses up with a string like "100 mbps" for the bandwidth field. Should I do the same here?


已移除自定义 QUIC 接收窗口大小,改用 quic-go 默认值。

我可以加上 force-brutal。Hysteria2 的带宽字段叫 up,格式是 "100 mbps" 这样的字符串。这里也这样做可以吗?

@LjhAUMEM
Copy link
Contributor

@RPRX 我想的是除了协商的 brutal 剩下的都可以接过来,但 force 可能要一个新的字段,和 hy 一样 up 还是

@Katze-942 Katze-942 changed the title XHTTP transport: Add BBR congestion control for H3 XHTTP transport: Add BBR and brutal-force congestion control for H3 Feb 24, 2026
@Katze-942
Copy link
Author

Ok, I've added the force-brutal algorithm with the "up" field for now.


好的,我暂时添加了 force-brutal 算法和 "up" 字段。

@RPRX
Copy link
Member

RPRX commented Feb 24, 2026

卧槽一会儿没看把 brutal 加给 XHTTP/3 了

要不把所有这些东西都在 tlsSettings 里开一个 "quic": {} 放进去吧,@LjhAUMEM 这样是否可行

@Katze-942
Copy link
Author

卧槽一会儿没看把 brutal 加给 XHTTP/3 了

Haha, it's not exactly brutal. It's force-brutal, I'll add brutal support in another PR.


哈哈,这不完全是 brutal。这是 force-brutal,我会在另一个 PR 中添加 brutal 的支持。

@Katze-942
Copy link
Author

要不把所有这些东西都在 tlsSettings 里开一个 "quic": {} 放进去吧,@LjhAUMEM 这样是否可行

I'd really like to move this to quic, because right now these settings look a bit out of place in xhttpSettings:


我确实想把这些移到 quic 里,因为目前这些设置放在 xhttpSettings 里看起来不太合适:

  "xhttpSettings": {                                                                          
    "quic": {                                                                                 
      "congestion": "force-brutal",
      "up": "100 mbps"
    }
  }

@LjhAUMEM
Copy link
Contributor

LjhAUMEM commented Feb 25, 2026

卧槽一会儿没看把 brutal 加给 XHTTP/3 了

要不把所有这些东西都在 tlsSettings 里开一个 "quic": {} 放进去吧,@LjhAUMEM 这样是否可行

也可以,如果他愿意做的话

I'll add brutal support in another PR.

no need to add brutal, xhttp3 is an unauth transport, but force-brutal can be added

I'd really like to move this to quic, because right now these settings look a bit out of place in xhttpSettings:

Then move the settings to TLS, or keep only the default bbr part (including temporarily removing force-brutal, congestion configuration) and this PR can be merged.

@Katze-942
Copy link
Author

Moved settings to "tlsSettings": { "quic": {} }


将设置移至 "tlsSettings": { "quic": {} }

@LjhAUMEM
Copy link
Contributor

LjhAUMEM commented Feb 26, 2026

looks good to me

@RPRX 剩下的我再移也行,对话效率有点低

@Fangliding
Copy link
Member

looks good to me

@RPRX 剩下的我再移也行,对话效率有点低

话说你看过 #5712

@LjhAUMEM
Copy link
Contributor

话说你看过 #5712

刚刚才看到,最近没关注 issue,那个艾特不知道是我邮件没有还是看漏了,应该是 break 了配置导致 udpmask 没设置上

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

@LjhAUMEM Hysteria 传输层除了 version、auth、udphop 以外的参数都能移到新地方对吧

@Fangliding
Copy link
Member

反正整个 TransportSettings 都是可读的 无聊的话放到wssettings都行 或者专门整个 TransportSettings.QUICParam (为啥放到tls里 因为QUIC用TLS传递window之类的流控参数?不过 brutal 参数不是)

@LjhAUMEM
Copy link
Contributor

LjhAUMEM commented Mar 2, 2026

@LjhAUMEM Hysteria 传输层除了 version、auth、udphop 以外的参数都能移到新地方对吧

congestion 的话要带 up down,剩下的就是 quic 类 (9-16)

为啥放到tls里

单纯就是移 congestion 顺带移 quic,因为 congestion 放 xhttp 似乎不合适

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

主要是放 xhttpSettings 里的话和 hysteriaSettings 里都是重复的内容那看起来很不优雅,然后我想了下放 tlsSettings 里也有同样的问题毕竟 REALITY 以后可能也支持 QUIC,还是单独弄一个 quicSettings 吧,这下秽土转生了

@Fangliding
Copy link
Member

我之前提的时候刻意写的 QUICParam 不和正常的传输设置搞混了

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

这个我也想过不过没对齐也有点不优雅,但防止搞混还是不对齐吧,quicParams 这样?

@Fangliding
Copy link
Member

em 我按着里面变量名命名打的 外面 config 肯定长这样

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

缺点就是不放 xhttpSettings 的话又要分享 JSON 了,要不把它扔 finalmask 里然后以后再挑些 sockopt 扔进去?

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

这样一来只是方便分享、蹭一下现有的 fm 参数,不过看着会有点怪,像是底层的 finalmask 影响到上层的 quic 了,不过以后 finalmask 挑些 sockopt 加进来再加上它本来就区分了 tcp/udp、v4/v6 的话 sockopt 倒是不违和

@Fangliding
Copy link
Member

哦还有一个问题 extra 只能写xhttpSettings
那算了还是分开放吧 毕竟目前只重复了两份 我记的以前是说法是三份以上再想办法来着

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

以后肯定会重复的,尤其是 REALITY 加了 QUIC 后,连 RAW 都能 QUIC 了,总不能再 copy 给 RAW 一份

有没有一种可能有人会希望对 v4/v6 应用不同的 quicParams,但是考虑到这个的话 TLS 会不会也有这种需求

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

还是先放 finalmask 里面吧,可以蹭到分享链接,这 finalmask 正在吸收越来越多的东西,以后还会有一些 sockopt

@Fangliding
Copy link
Member

quicparam 不也是分享链接么

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

主要你得想多个这东西的话 GUI 上又要多个框,现在连 fm 的框都还没加完,而且这东西没啥价值啊可能根本就没有人去改

Hy2 自带分享链接规范的倒不用管它

@RPRX
Copy link
Member

RPRX commented Mar 2, 2026

之前本来说想给 sockopt 也弄个 json 分享但同样是价值不高,为此 GUI 上又多个默认的框就不值得,况且 sockopt 还有是否仅本地适用问题和 tcp/udp、v4/v6 问题,所以以后选一些能分享的融进 fm 是最好的选择

@RPRX RPRX mentioned this pull request Mar 2, 2026
@Katze-942
Copy link
Author

Okay, so should I move the QUIC settings to finalmask?


好的,那我把 QUIC 设置移到 finalmask 里?

@RPRX
Copy link
Member

RPRX commented Mar 3, 2026

@Katze-942 是的,在 finalmask 内开个 "quicParams": {}虽然这看起来有点怪但确实分享起来很方便

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants